using IGeekFan.AspNetCore.Knife4jUI;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.IdentityModel.Tokens;
using Microsoft.OpenApi.Models;
using Newtonsoft.Json;
using System.IdentityModel.Tokens.Jwt;
using System.Reflection;
using System.Text;
using WCS.Api.Admin.Filter;
using WCS.Infrastructure.Dto.Response.Common;
using WCS.Infrastructure.EFCore;
using WCS.Infrastructure.IOC;
using WCS.Infrastructure.Tools;
using WCS.Repository.Instance;
using WCS.Repository.Interface;
using WCS.Service.Instance;
using WCS.Service.Interface;


var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddControllers();
builder.Services.AddControllersWithViews();
builder.Services.AddSwaggerGen();

builder.WebHost.UseUrls(builder.Configuration["Post"]);

#region Cors跨域请求
builder.Services.AddCors(c =>
{
    c.AddPolicy("AllRequests", policy =>
    {
        policy
        //.WithOrigins("http://127.0.0.1:5001")
        .AllowAnyOrigin()//允许所有接口访问
        .AllowAnyMethod()
        //.WithMethods("GET", "POST", "PUT", "DELETE", "OPTIONS") // 明确列出允许的方法
        .AllowAnyHeader();
    });
});
#endregion

// PostgreSQL 的配置 （使用AddDbContextPool可以减少并发，目前没使用）
builder.Services.AddDbContext<wcsDbContext>(options =>
{
    var connectionString = builder.Configuration.GetConnectionString("Default");
    options.UseNpgsql(connectionString, npgsqlOptions =>
    {
        // 设置超时时间，最小和最大连接池大小
        npgsqlOptions.CommandTimeout(120);
        npgsqlOptions.MaxBatchSize(100);
        npgsqlOptions.MinBatchSize(5);
        // 启用连接重试
        //npgsqlOptions.EnableRetryOnFailure(maxRetryCount: 3, maxRetryDelay: TimeSpan.FromSeconds(5), errorCodesToAdd: null);
    });
    //禁用跟踪
    //options.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking);
});

// 用 Scoped 工厂维持 DbContext -> wcsDbContext 的映射（替代原来的 AddDbContext<DbContext, wcsDbContext>）
builder.Services.AddScoped<DbContext>(sp => sp.GetRequiredService<WCS.Infrastructure.EFCore.wcsDbContext>());

//builder.Services.AddDbContext<DbContext, WCS.Infrastructure.EFCore.wcsDbContext>();

builder.Services.AddScoped(typeof(IRepository<>), typeof(SqlRepository<>));
builder.Services.AddScoped<IUnitOfWork, EfCoreUnitOfWork>();//注册事务
builder.Services.AddScoped(Assembly.Load("WCS.Service.EFCore"), Assembly.Load("WCS.Service.EFCore"));
builder.Services.AddScoped(Assembly.Load("WCS.Service.Interface"), Assembly.Load("WCS.Service.Instance"));
builder.Services.AddScoped(Assembly.Load("WCS.Infrastructure.IOC"), Assembly.Load("WCS.Infrastructure.IOC"));

//获取IP注入
builder.Services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
// 注册定时结算后台服务
builder.Services.AddHostedService<AtRegularTimeBackgroundService>();

// 注册新的模拟订单服务
//builder.Services.AddHostedService<OrderSimulationBackgroundService>();

#region Swagger

builder.Services.AddSwaggerGen(options =>
{
    options.SwaggerDoc("v1", new OpenApiInfo()
    {
        Title = "WCS.Api",
        Version = "v1.0",
        Description = "惠旺店.接口文档",
        Contact = new OpenApiContact
        {
            Name = "csp",
            Url = new Uri("http://localhost:7152"),
        },
    });
    string basePath = Path.GetDirectoryName(typeof(Program).Assembly.Location);
    string xmlPath = Path.Combine(basePath, "WCS.Api.Admin.xml");
    //options.IncludeXmlComments(xmlPath, true);
    options.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, "WCS.Api.Admin.xml"), true);

    options.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, "WCS.Infrastructure.Dto.xml"), true);

    options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
    {
        Description = "JWT授权(数据将在请求头中进行传输) 直接在下框中输入Bearer {token}（注意两者之间是一个空格,正确格式为 Bearer+空格+Token）\"",
        Name = "Authorization",
        In = ParameterLocation.Header,
        Type = SecuritySchemeType.ApiKey
    });

    options.AddSecurityRequirement(new OpenApiSecurityRequirement {

                {
                    new OpenApiSecurityScheme
                {
                Reference = new OpenApiReference()
                {
                Id = "Bearer",
                Type = ReferenceType.SecurityScheme
                }
                }, Array.Empty<string>() }
                });

});
#endregion

builder.Services.AddControllers(options =>
{
    //options.Filters.Add<StaticRoleAuthorizationFilter>();// 全局静态权限过滤器
    options.Filters.Add(typeof(WCS.Api.Admin.Filter.ActionFilter));//行为日志过滤器注入
});

//var provider = builder.Services.BuildServiceProvider();//手动注入（DbContext并发）服务生命周期、单例等出现问题

// 添加内存缓存服务
builder.Services.AddMemoryCache();
builder.Services.AddHttpContextAccessor();

//分布式缓存服务 使用内存缓存（仅适合单机开发测试）
builder.Services.AddDistributedMemoryCache();
//使用 Redis 作为分布式缓存
//services.AddStackExchangeRedisCache(options =>
//{
//    options.Configuration = "localhost:6379"; // Redis连接字符串
//    options.InstanceName = "WCS:";
//});

//配置jwt的验证规则 使用的bearer
string jwtKey = builder.Configuration["JWT:issuer"];
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
 .AddJwtBearer(options =>
 {
     options.TokenValidationParameters = new TokenValidationParameters
     {
         ValidateIssuer = true,
         ValidateAudience = true,
         ValidateLifetime = true,
         ValidateIssuerSigningKey = true,
         //ValidAudience = jwtKey,
         //ValidIssuer = jwtKey,
         ValidAudiences = new[] { jwtKey },
         ValidIssuers = new[] { jwtKey, "http://*:7152", "http://*:7153" },
         ClockSkew = TimeSpan.FromMinutes(5),//TimeSpan.FromSeconds(60),
         IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration["JWT:SecurityKey"]))
     };

     options.Events = new JwtBearerEvents
     {
         //自定义验证规则
         OnMessageReceived = async context =>
         {
             try
             {
                 string auth = context.Request.Headers["Authorization"];
                 if (!string.IsNullOrEmpty(auth))
                 {
                     var token = new JwtSecurityTokenHandler().ReadJwtToken(auth.Substring(7));//获取token保存的内容
                     var code = token.Claims.ToList().First(o => o.Type == System.Security.Claims.ClaimTypes.Name).Value.ToString();

                     //var userService = provider.GetService<IUserService>() as IUserService;
                     // 使用请求作用域的服务提供者
                     var userService = context.HttpContext.RequestServices.GetService<IUserService>();
                     var user = await userService.GetUserByCodeAsync(code);
                     if (user.code == ApiCode.fail)
                     {
                         context.Request.Headers["Authorization"] = string.Empty;
                     }
                     else
                     {
                         if (user.code == ApiCode.ok && user.data != null)
                         {
                             // 将用户信息存储在HttpContext.Items中，而不是静态变量
                             context.HttpContext.Items["CurrentUser"] = user.data;

                             //// 依据返回的是 B 端用户还是 C 端用户，进行类型检查
                             //if (user.data is SysUser)
                             //{
                             //    Config.UserId = ((SysUser)user.data).Id;
                             //}
                             //else if (user.data is SysUserMiniProgram)
                             //{
                             //    Config.UserId = ((SysUserMiniProgram)user.data).Id;
                             //}
                         }
                         //else
                         //{
                         //    Config.UserId = "";
                         //}
                     }
                 }
             }
             catch (Exception e)
             {
                 context.Request.Headers["Authorization"] = string.Empty;
             }

             //return Task.CompletedTask;
         }
     };

 });


var app = builder.Build();

app.Use((context, next) =>
{
    context.Request.EnableBuffering();
    return next(context);
});

app.UseMiddleware<WCS.Api.Admin.MiddleWares.ExceptionMiddle>();//异常处理中间件
app.UseMiddleware<IpRestrictionMiddleware>();

//UseKnife4UI接口文档
app.UseKnife4UI(d =>
{
    d.RoutePrefix = String.Empty;
    d.SwaggerEndpoint("/swagger/v1/swagger.json", "v1");
});

app.UseCors("AllRequests");


app.UseSwagger();
app.UseSwaggerUI(c =>
{
    c.SwaggerEndpoint("/swagger/v1/swagger.json", "v1");
});


// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
    //app.UseExceptionHandler("/Home/Error");//注释原因和自定义异常处理中间件冲突
    // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();  

app.UseAuthentication();//鉴权
app.UseAuthorization();//授权

app.MapControllerRoute(
    name: "default",
    pattern: "{controller=Home}/{action=Index}/{id?}");

app.Run();
